require 'redis'
require 'json'
require 'time'
require 'forwardable'
require 'proxy_pump/connection_pool'
module ProxyPump
  class Cache

    extend Forwardable

    attr_reader :options

    def_delegator :connection_pool, :with_connection

    def initialize(options)
      @options   = options
      @pool_size = options.fetch(:pool, 2)
      @namespace = options.fetch(:namespace, 'proxy_pump')
    end

    def all
      with_connection { |redis| redis.smembers(@namespace).map { |json| JSON.parse(json).symbolize_keys } }
    end

    def add(*proxies)
      with_connection do |redis|
        proxies.each do |proxy|
          proxy = proxy.to_h
          proxy[:created_at]       = Time.parse(proxy[:created_at]).iso8601       if proxy[:created_at]
          proxy[:updated_at]       = Time.parse(proxy[:updated_at]).iso8601       if proxy[:updated_at]
          proxy[:last_verified_at] = Time.parse(proxy[:last_verified_at]).iso8601 if proxy[:last_verified_at]
          redis.sadd @namespace, JSON.dump(proxy)
        end
      end
    end

    def remove(*proxies)
      with_connection do |redis|
        cached = redis.smembers(@namespace).map { |json| JSON.parse(json).symbolize_keys }
        proxies.map(&:to_h).each { |proxy| cached.reject! { |item| item[:host] == proxy[:host] && item[:port] == proxy[:port] } }
        redis.del @namespace
        cached.each { |proxy| redis.sadd @namespace, JSON.dump(proxy) }
      end
    end

    def clear
      with_connection { |redis| redis.del @namespace }
    end

    def shutdown(&block)
      @connection_pool.shutdown(&block) if @connection_pool
    end
    alias_method :close, :shutdown

    private

      def connection_pool
        @connection_pool ||= ConnectionPool.new(size: @pool_size) { Redis.new options }
      end

  end # Cache
end # PxPump
